package com.dreamers.core;

import java.awt.*;
import java.awt.image.BufferStrategy;

public class EngineRunnable extends Canvas implements Runnable {
    public static final float UPDATE_RATE = 60.0f;
    public static final long SECOND = 1000000000L;
    public static final float UPDATE_INTERVAL = SECOND / UPDATE_RATE;
    public static final long IDLE_TIME = 1;

    boolean isStart = true;

    public EngineRunnable() {
        this.setBounds(0, 0, Global.GAMEWIDTH, Global.GAMEHEIGHT);
    }

    public void start() {
        if (IAwakeListener.iAwakeListenerList.size() > 0) {
            for (IAwakeListener iAwakeListener : IAwakeListener.iAwakeListenerList) {
                iAwakeListener.Awake();
            }
        }

        if (IStartListener.iStartListenerList.size() > 0) {
            for (IStartListener iStartListener : IStartListener.iStartListenerList) {
                iStartListener.start();
            }
        }

        if (IKeyListener.iKeyListenerList.size() > 0) {
            for (IKeyListener iKeyListenerManager : IKeyListener.iKeyListenerList) {
                this.addKeyListener(iKeyListenerManager);
            }
        }
        if (IMouseListener.iMouseListenerList.size() > 0) {
            for (IMouseListener iMouseListenerManager : IMouseListener.iMouseListenerList) {
                this.addMouseListener(iMouseListenerManager);
            }
        }
        if (IMouseWheelListener.iMouseWheelListenerList.size() > 0) {
            for (IMouseWheelListener iMouseWheelListener : IMouseWheelListener.iMouseWheelListenerList) {
                this.addMouseWheelListener(iMouseWheelListener);
            }
        }
    }


    @Override
    public void run() {
        if (isStart) {
            start();
        }
        update();
    }

    private void update() {
        long count = 0;
        float delta = 0;
        long lastTime = getCurrentSystemTime();
        while (true) {
            long now = getCurrentSystemTime();
            long elapsedTime = now - lastTime;
            lastTime = now;
            count += elapsedTime;
            boolean render = false;
            delta += (elapsedTime / UPDATE_INTERVAL);
            while (delta > 1) {
                this.tick();
                this.render();
                delta--;
                if (render) {
                } else {
                    render = true;
                }
            }
            if (render) {
            } else {
                try {
                    Thread.sleep(IDLE_TIME);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            if (count >= SECOND) {
                count = 0;
            }

        }
    }


    public void render() {
        BufferStrategy bs = this.getBufferStrategy();
        if (bs == null) {
            this.createBufferStrategy(3);
            return;
        }
        Graphics g = bs.getDrawGraphics();
        g.setColor(Color.white);
        g.fillRect(0, 0, Global.GAMEWIDTH, Global.GAMEHEIGHT);

        if (IRenderListener.iRenderListenerList.size() > 0) {
            for (IRenderListener iRenderListener : IRenderListener.iRenderListenerList) {
                iRenderListener.render(g);
            }
        }

        g.dispose();
        bs.show();
    }


    public void tick() {
        if (ITickListener.iTickListenerList.size() > 0) {
            for (ITickListener iTickListener : ITickListener.iTickListenerList) {
                iTickListener.tick();
            }
        }
    }

    public long getCurrentSystemTime() {
        return System.nanoTime();
    }
}
